package com.sdcqjy.mylibrary.http;

import android.text.TextUtils;

import com.sdcqjy.mylibrary.Logger;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * 统一网络访问
 * 用于继承的
 */
public class HttpClient {
    private static Dispatcher dispatcher;
    private static OkHttpClient okHttpClient;
    public static ExecutorService executorService;
    public static final int HttpOnResponse = 1;//请求成功
    public static final int HttpOnFailure = 2;//请求失败
    public static final int HttpOnCanceled = 3;//请求取消

    //自定义线程池大小，可以不用
    public static Dispatcher getDispatcher() {
        if (dispatcher == null) {
            executorService = new ScheduledThreadPoolExecutor(4);
            dispatcher = new Dispatcher(executorService);
        }
        return dispatcher;
    }

    //初始化okHttp
    private static void initHttpClient() {
        if (okHttpClient == null) {
            synchronized (HttpClient.class) {
                if (okHttpClient == null) {
                    OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(600, TimeUnit.SECONDS).dispatcher(getDispatcher());
                    if (Logger.isDebug) {
                        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                            public void log(String message) {
                                Logger.i("OkHttpClient", "OkHttpMessage:" + message);
                            }
                        });
                        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                        builder.addInterceptor(logInterceptor);
                    }
                    okHttpClient = builder.build();
                }
            }
        }
    }

    public static OkHttpClient getOkHttpClient() {
        initHttpClient();
        return okHttpClient;
    }

    public HttpClient() {
        initHttpClient();
    }

    public void httpRequest(String url, RequestBack requestBack) {
        if (TextUtils.isEmpty(url)) return;
        this.requestBack = requestBack;
        //Logger.v("--请求url--", url);
        RequestBody requestBody = null;
        Request.Builder builder1 = new Request.Builder();
        builder1.addHeader("Dev", "Android");
        //添加Header
        if (headers != null && headers.size() > 0) {
            //if (Logger.isDebug) Logger.v("--httpHeaders--", param.toString());
            Set<String> strings = headers.keySet();
            for (String key : strings) builder1.addHeader(key, headers.get(key));
        }
        String method = "POST";
        if (httpType == HttpType.JSON) {//JSON其实是POST请求另一种方式,常用于ajax
            MediaType JSON = MediaType.parse("application/json; charset=utf-8");
            String jsonStr = "{}";
            if (param != null) jsonStr = new JSONObject(param).toString();
            //Logger.v("--请求json--", jsonStr);
            requestBody = RequestBody.create(JSON, jsonStr);
        } else if (httpType == HttpType.GET) {
            method = "GET";
            if (param != null && param.size() > 0) {
                StringBuffer buffer = new StringBuffer();
                buffer.append(url);
                if (url.contains("?")) {
                    buffer.append('&');
                } else buffer.append('?');
                Set<String> set = param.keySet();
                for (String key : set) {
                    buffer.append(key).append("=").append(param.get(key)).append('&');
                }
                url = buffer.toString();
                //这是去除结尾多出来的&符号，但也可以不去除
                //url = url.substring(0, url.length() - 1);
                //Logger.v("--追加参数后的url--", url);
            }
        } else if (httpType == HttpType.POST) {
            if (param != null && param.size() > 0) {
                FormBody.Builder builder = new FormBody.Builder();
                //if (Logger.isDebug) Logger.v("--post参数--", param.toString());
                Set<String> set = param.keySet();
                for (String key : set) builder.add(key, param.get(key).toString());
                requestBody = builder.build();
            }
        } else if (httpType == HttpType.POST_Form) {
            if (param != null && param.size() > 0) {
                MultipartBody.Builder builder = new MultipartBody.Builder();
                builder.setType(MultipartBody.FORM);
                //if (Logger.isDebug) Logger.v("--post参数--", param.toString());
                Set<String> set = param.keySet();
                for (String key : set) {
                    Object o = param.get(key);
                    if (o instanceof File) {
                        File file = (File) o;
                        // MediaType.parse() 里面是上传的文件类型。
                        RequestBody body = RequestBody.create(MediaType.parse("image/*"), file);
                        // 参数分别为， 请求key ，文件名称 ， RequestBody
                        builder.addFormDataPart(key, file.getName(), body);
                    } else builder.addFormDataPart(key, o.toString());
                }
                requestBody = builder.build();
            }
        }
        Request build = builder1
                .url(url)
                //这里通常写.get或.post实际上是method("GET", null);或method("POST", requestBody);
                .method(method, requestBody)
                .build();
        call_ = okHttpClient.newCall(build);
        call_.enqueue(callback);//异步执行
        //call_.execute();这是同步执行，需要创建线程。那之前自定义的线程池就没有意义了
    }

    private Callback callback = new Callback() {
        public void onFailure(Call call, IOException e) {
            call_ = null;
            if (e != null && ("Socket closed".equals(e.getMessage()) || "Canceled".equals(e.getMessage()))) {
                Logger.v("---网络请求---", "------请求取消-----");
                if (requestBack != null) {
                    try {
                        requestBack.onResponse(HttpOnCanceled, "请求取消");
                    } catch (Exception e1) {
                        if (Logger.isDebug) e1.printStackTrace();
                    }
                }
                if (Logger.isDebug) e.printStackTrace();
            } else {
                if (requestBack != null) {
                    try {
                        requestBack.onResponse(HttpOnFailure, "网络异常");
                    } catch (Exception e1) {
                        if (Logger.isDebug) e1.printStackTrace();
                    }
                }
            }
        }

        public void onResponse(Call call, Response response) throws IOException {
            //异步回调成功时返回，注意此时是由子线程返回的
            call_ = null;
            if (response.isSuccessful()) {
                String jsonString = response.body().string();
                //Logger.out("---返回数据---" + jsonString);
                if (requestBack != null) {
                    try {
                        requestBack.onResponse(HttpOnResponse, jsonString);
                    } catch (Exception e) {
                        if (Logger.isDebug) e.printStackTrace();
                        onFailure(null, null);
                    }
                }
            } else {
                //Logger.out("---response.code---" + response.code());
                onFailure(null, null);
            }
        }
    };

    private Map<String, Object> param;//访问参数
    private Map<String, String> headers;//访问http头
    private int httpType = HttpType.GET;//网络访问类型

    public HttpClient setParam(Map<String, Object> param) {
        if (this.param == null)
            this.param = param;
        else this.param.putAll(param);
        return this;
    }

    public HttpClient addParam(String key, Object obj) {
        if (TextUtils.isEmpty(key) || obj == null) return this;
        if (param == null) param = new HashMap<>();
        param.put(key, obj);
        return this;
    }

    public HttpClient setHeaders(Map<String, String> headers) {
        this.headers = headers;
        return this;
    }

    /**
     * 默认GET请求
     *
     * @param httpType
     */
    public HttpClient setHttpType(int httpType) {
        this.httpType = httpType;
        return this;
    }

    public boolean isStop;
    private Call call_;
    private RequestBack requestBack;

    public void stop() {
        if (call_ != null) call_.cancel();
        isStop = true;
    }

    public interface RequestBack {
        void onResponse(int retType, String retStr) throws Exception;
    }

    public static class HttpType {
        public static final int GET = 0;
        public static final int POST = 1;
        public static final int POST_Form = 2;
        public static final int JSON = 3;
    }
}
